package com.cjj2016.cjj.mylyricviewdemo.widget;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.OvershootInterpolator;

import com.cjj2016.cjj.mylyricviewdemo.model.LineInfo;
import com.cjj2016.cjj.mylyricviewdemo.model.LyricInfo;

import java.text.DecimalFormat;


/**
 * Created by CJJ on 2017/1/17.
 */

public class MyLyricView extends View {
    private static final String TAG = "MyLyricView";

    //隐藏绘制的播放按钮消息
    public static final int MSG_PLAYER_HIDE = 1;

    //歌词文字paint
    private Paint textpaint;

    //指示器paint
    private Paint linePaint;

    //播放按钮paint
    private Paint btnPaint;

    //歌词信息
    private LyricInfo mLyrcInfo;

    private String mDefaultLyric="暂无歌词";

    //默认指示器右边的时间字符串
    private String mDefaultIndicatorTime = "00:00";

    //指示器时间的Rect
    private Rect indicatorTimeRect;

   // private List<String> songlist = new ArrayList<>();

    private int mLineCount;//歌词行数

    private int mLineHeight;//行高

    private float mScrollY;

    //手指按下的时的x值
    private float downX;

    //手指按下的时的Y值
    private float downY;

    //上一次的ScrollY
    private float mLastScrollY;

    //用户是否按下标识
    private boolean mUserTouch=false;

    //是否显示指示器
    private boolean mShowIndicator=false;

    private float maxScrollHeight;//最大的滚动距离

    //最大的阻尼距离，超过这个值阻尼值越大。
    private final int mMaxDampingDistance = 300;

    //速率追踪器
    private VelocityTracker velocityTracker;

    // 最大纵向滑动速度
    private int maximumFlingVelocity;

    // 最低滑动的速率
    private int mMinStartUpSpeed = 800;

    //当前滑动的速率
    private float mVelocity;

    //滑行动画实例
    private ValueAnimator flyAnimator;

    //当前播放的行
    private int mCurrentPlayLine;

    // 默认字体颜色
    private int mDefaultTextColor = Color.parseColor("#FFFFFF");

    // 当前行的颜色
    private int mCurrentLineTextColor = Color.parseColor("#4FC5C7");

    //当前指示器指定行的颜色
    private int mIndicatorLineColor=Color.parseColor("#AAAAAA");


    //歌词渐变高度
    private float mShaderHeight;

    //滚动区域的上边界
    private float mScrollTopBound;

    //当前指示器指定的行数
    private int mIndicatorLine;

    //绘制播放按钮的宽高
    private int btnRectWidth;

    //播放按钮的rect
    Rect btnRect;

    private invaldatePlayListener mPlayListener;

    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case MSG_PLAYER_HIDE:
                    mShowIndicator = false;
                    invalidate();
                    //Log.i(TAG, "handleMessage: MSG_PLAYER_HIDE exec");
                    break;
            }
        }
    };

    public MyLyricView(Context context) {
        super(context);

        initView(context);
    }

    public MyLyricView(Context context, AttributeSet attrs) {
        super(context, attrs);

        initView(context);
    }


    public MyLyricView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        initView(context);
    }


    private void initView(Context context) {

        maximumFlingVelocity = ViewConfiguration.get(context).getScaledMaximumFlingVelocity();

//        for(int i=1; i<=60; i++ )
//        {
//            songlist.add("歌词歌词歌词歌词歌词歌词歌词歌词"+i);
//        }
//
//        mLineCount = songlist.size();

        textpaint = new Paint();
        textpaint.setDither(true);
        textpaint.setAntiAlias(true);
        textpaint.setTextAlign(Paint.Align.CENTER);
        textpaint.setTextSize(45);

//        //计算每行的高度
//        Rect rect = new Rect();
//        textpaint.getTextBounds(mDefaultLyric,0,mDefaultLyric.length(),rect);
//
        //mLineHeight = rect.height()+ 30;

        linePaint = new Paint();
        linePaint.setDither(true);
        linePaint.setAntiAlias(true);
        linePaint.setTextAlign(Paint.Align.CENTER);
        linePaint.setColor(Color.GRAY);
        indicatorTimeRect = new Rect();
        linePaint.getTextBounds(mDefaultIndicatorTime,0,mDefaultIndicatorTime.length(),indicatorTimeRect);


        btnPaint = new Paint();
        btnPaint.setDither(true);
        btnPaint.setAntiAlias(true);
        btnPaint.setColor(Color.GRAY);
        btnPaint.setStrokeWidth(3.0f);
        btnPaint.setStyle(Paint.Style.STROKE);

        btnRectWidth=60;
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        //maxScrollHeight = (mLineCount+1) * mLineHeight - getMeasuredHeight();
//        maxScrollHeight = (mLineCount+1) * mLineHeight;
//
        mScrollTopBound = getMeasuredHeight() * 0.5f;

        mShaderHeight= getMeasuredHeight() * 0.3f;
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if( mLineCount > 0){
            for(int i=0; i< mLineCount ; i++ )
            {
                float x = getMeasuredWidth()/2;
                //float y = (i+1) * mLineHeight - mScrollY;
                float y = (i+1) * mLineHeight + getMeasuredHeight()*0.5f - mScrollY;

                //超出显示区域大小的，不绘制。
                if(y <0)
                    continue;
                if(y> getMeasuredHeight())
                    break;

                //当前播放行,设置画笔颜色
                if(i == (mCurrentPlayLine-1) ){
                    //当前行颜色
                    textpaint.setColor(mCurrentLineTextColor);
                }else{
                    if(mShowIndicator && i == mIndicatorLine){
                        //指示器指定行的颜色
                        textpaint.setColor(mIndicatorLineColor);
                    }else{
                        //正常颜色
                        textpaint.setColor(mDefaultTextColor);
                    }
                }

                //颜色渐变效果
                if( y< mShaderHeight ){
                    //上边渐变
                    textpaint.setAlpha( 26 + (int) (230.0f * y / mShaderHeight ) );
                }else if( y> (getMeasuredHeight() - mShaderHeight) ){
                    //下班渐变
                    textpaint.setAlpha( 26 + (int) (230.0f * (getMeasuredHeight()-y) / mShaderHeight ) );
                }else {
                    //正常
                    textpaint.setAlpha(255);
                }

                canvas.drawText(mLyrcInfo.song_lines.get(i).content,x,y,textpaint);
            }
        }else{
            //没有歌词信息
            canvas.drawText(mDefaultLyric,getMeasuredWidth()/2,getMeasuredHeight()/2,textpaint);
        }

        //手指按下时，画指示器
        if(mShowIndicator){
            drawIndicator(canvas);
            drawPlayer(canvas);
        }


    }


    //绘制左侧播放按钮
    private void drawPlayer(Canvas canvas) {

        btnRect = new Rect(10, (getMeasuredHeight()-btnRectWidth)/2-25
                ,10+btnRectWidth,getMeasuredHeight()/2 + btnRectWidth);

        float sradio = btnRectWidth * 0.5f;
        float swidth = (float) Math.sqrt( Math.pow(sradio,2)* 2 );
        float b= (float) Math.sqrt(Math.pow(swidth,2)-Math.pow(swidth/2,2));
        Path payerPath = new Path();
        payerPath.moveTo(  btnRect.centerX()- b+sradio,btnRect.centerY()-sradio/2);
        payerPath.lineTo(btnRect.centerX()- b+sradio,btnRect.centerY()+sradio/2);
        payerPath.lineTo( btnRect.centerX()+ sradio-10,btnRect.centerY());
        payerPath.lineTo( btnRect.centerX()- b+sradio,btnRect.centerY()-sradio/2 );
        canvas.drawPath(payerPath,btnPaint); //绘制播放三角形

        canvas.drawCircle(btnRect.centerX(),btnRect.centerY(),btnRectWidth*0.5f,btnPaint);
    }


    //绘制指示器
    private void drawIndicator(Canvas canvas){
        //当前指示器指的行数
        mIndicatorLine = (int) (mScrollY/mLineHeight);

        linePaint.setStyle(Paint.Style.FILL);
        linePaint.setTextSize(40);
        canvas.drawText(measureCurrentTime(),getMeasuredWidth()-indicatorTimeRect.width()-20
                ,(getMeasuredHeight()+indicatorTimeRect.height())*0.5f+10,linePaint);

        linePaint.setStrokeWidth(2.0f);//画笔的宽度
        linePaint.setStyle(Paint.Style.STROKE);
        linePaint.setPathEffect(new DashPathEffect(new float[]{20,10},0));
        Path path = new Path();
        path.moveTo( btnRectWidth +20,getMeasuredHeight()/2);
        path.lineTo(getMeasuredWidth() - indicatorTimeRect.width()-80
                ,getMeasuredHeight()/2);
        canvas.drawPath(path,linePaint);
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
       //初始化速率追踪器，并添加追踪当前的TouchEvent
        if(velocityTracker ==null){
            velocityTracker = VelocityTracker.obtain();
        }
        velocityTracker.addMovement(event);

        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                actionDown(event);
                break;
            case MotionEvent.ACTION_MOVE:
                actionMove(event);
                break;
            case MotionEvent.ACTION_UP:
                actionUp(event);
                break;
        }

        invalidate();
        return true;
    }




    private void actionDown(MotionEvent event) {

        //取消正在滑动的动画
        if(flyAnimator !=null){
            flyAnimator.cancel();
            flyAnimator =null;
        }

        //移除隐藏绘制的播放按钮消息。
        handler.removeMessages(MSG_PLAYER_HIDE);

        mLastScrollY = mScrollY;
        downX = event.getX();
        downY =  event.getY();

        mUserTouch =true;

        mShowIndicator=true;
       // Log.i(TAG, "actionDown: mLastScrollY="+mLastScrollY);
    }

    private void actionMove(MotionEvent event) {

        velocityTracker.computeCurrentVelocity(1000,maximumFlingVelocity);
        mVelocity = velocityTracker.getYVelocity();//获取y轴的速率

        float offsetY = downY - event.getY();
        float scrolly = mLastScrollY + offsetY;
        mScrollY =scrolly;

        //Log.i(TAG, "actionMove: mScrollY="+mScrollY);

        if( offsetY < -20 )
        {
            //手指往下滑，列表上上
            if(mScrollY < 0 ){
                mScrollY = 0 - measureDampingDistance( Math.abs(scrolly) );
                //Log.i(TAG, "actionMove: toprollback,mScrollY="+mScrollY);
                return;
            }


        }else if( offsetY > 20){
            //手指网上滑，列表向下

            if( mScrollY >= maxScrollHeight){
                mScrollY = maxScrollHeight + measureDampingDistance( (scrolly- maxScrollHeight) );
                //Log.i(TAG, "actionMove: endrollback,mScrollY="+mScrollY+",maxScrollHeight="+maxScrollHeight);
                return;
            }

        }

    }

    private void actionUp(MotionEvent event) {
        mUserTouch =false;
        //延迟3s，发送隐藏绘制的播放按钮消息。
        handler.sendEmptyMessageDelayed(MSG_PLAYER_HIDE,3000);

        if(mScrollY < 0){
            //超过了上边界，需要回弹
            smoothScrollTo(0);
            return;
        }

        if(mScrollY >= maxScrollHeight){
            //超过了下边界，需要回弹
            //smoothScrollTo((mLineCount+1) * mLineHeight - getMeasuredHeight());
            smoothScrollTo(maxScrollHeight);
            return;
        }

        //滑动速率超过最小值后，需要滑动一段距离
        if( Math.abs(mVelocity) > mMinStartUpSpeed){
            doFlyingAnimation(mVelocity);
            return;
        }

        //判断是否显示了指示器，并且点击了播放按钮
        if(mShowIndicator && clickPlay(event)){
            if( mIndicatorLine != mCurrentPlayLine){
                mShowIndicator = false;
                if(mPlayListener !=null){
                    mPlayListener.playTime(mLyrcInfo.song_lines.get(mIndicatorLine).start);
                }

                //Log.i(TAG, "actionUp: bofang ");
            }

        }

    }




    /**
     * 根据速率，滑动一段距离
     * @param velocity
     */
    private void doFlyingAnimation(float velocity) {
        float distance = (velocity / Math.abs(velocity) * Math.min((Math.abs(velocity) * 0.50f), 1000));   // 计算就已当前的滑动速度理论上的滑行距离是多少
        //float to = Math.min(Math.max(0, (mScrollY - distance)), maxScrollHeight);   // 综合考虑边界问题后得出的实际滑行距离
        float to = mScrollY - distance;

        if(to < 0 ){
            to = 0-50;
        }else if(to > maxScrollHeight){
            to= maxScrollHeight + 50;
        }

        flyAnimator = ValueAnimator.ofFloat(mScrollY,to).setDuration(1000);
        flyAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mScrollY = (float) flyAnimator.getAnimatedValue();
                invalidate();
            }
        });
        flyAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                if(mScrollY < 0){
                    //超过了上边界，需要回弹
                    smoothScrollTo(0);
                    return;
                }

                if(mScrollY >= maxScrollHeight){
                    //超过了下边界，需要回弹
                    smoothScrollTo(maxScrollHeight);
                    return;
                }
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
        flyAnimator.setInterpolator(new DecelerateInterpolator());//减速运动
        flyAnimator.start();

    }


    private float measureDampingDistance2(float value) {
        return value> 50 ? (50 * 0.6f + (value - 50) * 0.2f) : value * 0.6f;
    }


    /**
     * 计算阻尼效果的大小
     * */
    private float measureDampingDistance(float value) {
        return value> mMaxDampingDistance ? (mMaxDampingDistance * 0.6f + (value - mMaxDampingDistance) * 0.2f) : value * 0.6f;
    }

    /**
     * 回滚动画
     * @param toY
     */
    private void smoothScrollTo(float toY) {
        final ValueAnimator animator = ValueAnimator.ofFloat(mScrollY , toY);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                if(mUserTouch) {
                    animator.cancel();
                    return;
                }
                mScrollY = (float) animation.getAnimatedValue();

                invalidate();
            }
        });

        animator.addListener(new AnimatorListenerAdapter() {

            @Override
            public void onAnimationStart(Animator animation) {
                super.onAnimationStart(animation);
            }

            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);

            }
        });
        animator.setDuration(640);
        animator.setInterpolator(new OvershootInterpolator(0.5f));

        animator.start();
    }



    //根据当前给定的时间，滑动到对应的位置
    private void scrollToCurrentTime(long time) {
        int postion=0;
        //遍历，获取当前时间戳对应的行数
        for(int i=0; i<mLineCount; i++){
            LineInfo lineInfo = mLyrcInfo.song_lines.get(i);
            if( lineInfo.start > time){
                postion = i;
                break;
            }
            if( i == mLineCount -1 ){
                postion = mLineCount;
            }
        }

        if( mCurrentPlayLine !=postion && !mShowIndicator ){
            mCurrentPlayLine = postion;
            smoothScrollTo( calcCurrentLineScrolly(postion) );
        }

    }

    /**
     * 计算行数对应的Scrolly
     * @param line
     * @return
     */
    private float calcCurrentLineScrolly(int line){
        return line * mLineHeight;
    }




    /**
     * 获取当前滑动到的位置,获取歌词对应的时间值
     * */
    private String measureCurrentTime() {
        DecimalFormat format = new DecimalFormat("00");
        if(mLyrcInfo != null && mLineCount > 0 && mIndicatorLine  < mLineCount && mIndicatorLine > 0) {
            return format.format(mLyrcInfo.song_lines.get(mIndicatorLine).start / 1000 / 60) + ":" + format.format(mLyrcInfo.song_lines.get(mIndicatorLine).start / 1000 % 60);
        }
        if(mLyrcInfo != null && mLineCount > 0 && mIndicatorLine >= mLineCount) {
            return format.format(mLyrcInfo.song_lines.get(mLineCount - 1).start / 1000 / 60) + ":" + format.format(mLyrcInfo.song_lines.get(mLineCount - 1).start / 1000 % 60);
        }
        if(mLyrcInfo != null && mLineCount > 0 && mIndicatorLine  <= 0) {
            return format.format(mLyrcInfo.song_lines.get(0).start / 1000 / 60) + ":" + format.format(mLyrcInfo.song_lines.get(0).start / 1000 % 60);
        }
        return mDefaultIndicatorTime;
    }


    /**
     * 判断是否点击了播放按钮
     * @param event
     * @return
     */
    private boolean clickPlay(MotionEvent event) {
//        Log.i(TAG, "clickPlay: btnRect left="+btnRect.left
//                +" ,right="+btnRect.right
//                +" ,top="+btnRect.top
//                +" ,bottom="+btnRect.bottom
//                +" ,downx="+downX
//                +" ,downY="+downY);

        if( downX > btnRect.left && downX < btnRect.right+10
                && downY > btnRect.top && downY< btnRect.bottom){
            float upX = event.getX();
            float upY = event.getY();
            return upX > btnRect.left && upX < btnRect.right+10
                    && upY > btnRect.top && upY< btnRect.bottom;
        }

        return false;
    }




    /**
     * ------------------------------------------------------------------------------------------------------- *
     *                对外API                                                                                   *
     * ------------------------------------------------------------------------------------------------------- *
     * */

    /**
     * 设置歌词信息
     * @param lyricInfo
     */
    public void setLyricInfo(LyricInfo lyricInfo){
        mLyrcInfo = lyricInfo;

        //总行数
        mLineCount = lyricInfo.song_lines.size();

        //计算每行的高度
        Rect rect = new Rect();
        textpaint.getTextBounds(mDefaultLyric,0,mDefaultLyric.length(),rect);
        mLineHeight = rect.height()+ 30;

        maxScrollHeight = (mLineCount+1) * mLineHeight;



        //请求重绘
        invalidate();

    }

    /**
     * 重置
     * @param msgstr
     */
    public void reset(String msgstr){
        mDefaultLyric = msgstr;

        mLyrcInfo=null;
        mScrollY=0;
        mLastScrollY=0;
        mLineCount=0;
        maxScrollHeight=0;
        mCurrentPlayLine = 0;
        mIndicatorLine=0;

        invalidate();
    }


    /**
     * 设置当前显示时间位置
     * @param current
     */
    public void setCurrentTime(long current){
        scrollToCurrentTime(current);
    }


    /**
     * 设置绘制的播放按钮的监听
     * @param listener
     */
    public void setInvaldatePlayListener(invaldatePlayListener listener){
        mPlayListener = listener;
    }


    /**
     * 绘制的播放按钮，点击监听接口
     */
    public interface invaldatePlayListener{
        void playTime(long time);
    }

}
